package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishFlavorService dishFlavorService;

    /**
     * 新增菜品功能
     * 进行两张表的操作，通过 dishService 操作 操作 dish 和 dish_flavor 两张关联的表
     * @param dishDto  中间 dto 类，保存两张表的数据
     */
    @Override
    @Transactional  //需要添加事务，因为这里涉及两张表，一个保存不成功，另一个也不能保存，必须回滚
    public void saveWithFlavor(DishDto dishDto) {
        //输出调试日志
        log.info("新曾菜品功能……操作两张数据表");

        //1. dish 菜品表的保存
        //直接进行保存菜品的信息到 dish 表
        //mp 框架回自动识别字段，dish 没有的字段自动排除掉
        this.save(dishDto);   //因为这里是 dishServiceImpl 里面，所以设个 dish 就是 dishServiceImpl（实现了dishService接口）

        //2. dish_flavor 口味表的保存，父表是 dish
        //因为父表是 dish，所以我们需要获取 父表的 id 进行赋值到子健 name_id上面去(dish_flavor 里面关联 dish 的字段)
        //获取 dish id
        Long id = dishDto.getId();   //因为 dto 继承了 dish，所以直接从 dto 获取，而且 id 是通过 uuid 生成的，所以需要先进行dish表的保存

        //通过 jdk 8 新特性stream()流，将 id 赋值到 dto 中的 flavor 的 list<DishFlavor> 集合中的 dishId
        //遍历 list 集合，将 id 添加进去  (lambda)
        //item 就是 每一个元素（dishFlavor对象）
        //lambda 格式   (参数) -> {要实现的方法内容 }
        List<DishFlavor> flavors = dishDto.getFlavors().stream().map((item) -> {
            item.setDishId(id);
            return item;   //不会修改原来的数据源，它会将操作后的数据保存到 item 对象
        }).collect(Collectors.toList());   //继续转成我们需要的集合

        //将 父表id 添加到集合 flavor 中后，可以直接添加保存到 数据库 dish_flavor 表中了
        dishFlavorService.saveBatch(flavors);  // saveBatch 参数是集合   ，batch 批量的意思
    }

    /**
     * 根据 菜品id 进行查找菜品对应的信息，以及口味
     *
     * @param id
     * @return
     */
    @Override
    @Transactional   //多表关联进行事务的开启
    public DishDto getByIdWithFlavor(Long id) {
        //输出日志调试
        log.info("菜品编辑回显功能……");

        //获取菜品的信息
        Dish dish = this.getById(id);

        //因为返回值只能有一个，所以我们 需要 DTO
        DishDto dishDto = new DishDto();
        //转移属性
        BeanUtils.copyProperties(dish,dishDto);

        //通过菜品的id获取口味的信息
        //创建条件查询
        LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper();
        //设置条件
        lambdaQueryWrapper.eq(DishFlavor::getDishId,id);

        //查询 sql 语句
        List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);

        //将 dishFlavorList 封装到 DTO 中
        dishDto.setFlavors(dishFlavorList);

        //返回 Dto 对象
        return dishDto;
    }

    /**
     * 更新菜品信息和口味信息之后的保存功能
     * @param dishDto 修改之后的菜品信息对象
     */
    @Override
    @Transactional  //多白哦操作就是，两张表各自完后自己的表的耿欣即可，绑定上 子健
    public void updateWithFlavor(DishDto dishDto) {
        //输出调试日志
        log.info("编辑菜品信息保存功能……数据：{}",dishDto);

        //更新dish表的基本信息
        this.updateById(dishDto);

        //清理当前的菜品的口味----dish_flavor表的delete操作
        LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //进行设置删除的条件
        lambdaQueryWrapper.eq(DishFlavor::getDishId,dishDto.getId());
        //执行删除口味的 sql 语句、
        dishFlavorService.remove(lambdaQueryWrapper);

        //进行设置更新之后的口味----dish_flavor表的insert操作
        List<DishFlavor> flavors = dishDto.getFlavors();

        //在 菜品口味的 flavors 集合中添加当前菜品的id ，进行绑定
        //这一步可有可无，因为 flavors 中已经有 dishId 的属性了，更新菜品 dishId 是不会变的，只有创建新菜品才会变
        flavors.stream().map((item) -> {
            //绑定 菜品 id
            item.setDishId(dishDto.getId());
            return item;
        }).collect(Collectors.toList());

        //设置完所有新的表的数据之后，将 更新之后的口味表进行 保存
        dishFlavorService.saveBatch(flavors);
    }
}
